home *** CD-ROM | disk | FTP | other *** search
/ Amiga Mag HDD Backup / Amiga Mag HDD Backup.zip / Amiga Mag HDD Backup / Alexander.img.bin / Alexander.img / tech 4.1 editorial Archive.sit / Griebling / Listing1 < prev    next >
Text File  |  1993-06-16  |  14KB  |  575 lines

  1. IMPLEMENTATION MODULE ExIntegers;
  2.  
  3. (*  Some Functions to perform bit manipulation on ExNumbers.
  4.     This module deals with integral ExNumbers in the range
  5.     from -5.9863E51 to 5.9863E51.  Any numbers outside this
  6.     range are represented with the maximum (or minimum)
  7.     ExNumber from this range.
  8. *)
  9.  
  10. FROM Conversions IMPORT ConvNumToStr, ConvStrToNum;
  11. FROM ExMathLib0  IMPORT xtoi;
  12. FROM ExNumbers   IMPORT ExNumType, ExChgSign, ExMin, ExMax,
  13.                         GetMaxDigits, Ex0, ExNumb, SignType,
  14.                         ExSub, Ex1, ExMult, ExDiv, IsZero,
  15.                         ExTrunc, ExAbs, ExStatus, ExStatusType,
  16.                         GetExpMant, ExDiv10, ExToLongInt,
  17.                         ExFrac, ExAdd, ExNumToStr,
  18.                         ExToLongCard, WriteExNum;
  19. FROM InOut       IMPORT WriteString, WriteLn, WriteLongInt,
  20.                         WriteCard;
  21. FROM Strings     IMPORT InsertSubStr, LengthStr;
  22.  
  23.  
  24. CONST
  25.   MaxBase2Bits = 172;    (* ln(9.99E51) / ln(2) *)
  26.   LogicalSize  = MaxBase2Bits DIV 16;
  27.   Left         = FALSE;
  28.   Right        = TRUE;
  29.  
  30. TYPE
  31.   LogicalType = ARRAY [0..LogicalSize] OF BITSET;
  32.   LogicalProc = PROCEDURE(BITSET, BITSET) : BITSET;
  33.   ExNumbProc  = PROCEDURE(VAR ExNumType, ExNumType, ExNumType);
  34.  
  35. VAR
  36.   LogZero   : LogicalType; (* All bits cleared or 0  *)
  37.   MaxNumber : ExNumType;   (*  2 ** MaxBase2Bits - 1 *)
  38.   MinNumber : ExNumType;   (* -2 ** MaxBase2Bits + 1 *)
  39.   Two       : ExNumType;   (* The value "2" *)
  40.   Cnt       : CARDINAL;
  41.  
  42.  
  43. (*--------------------------------------*)
  44. (* Local bit manipulations functions.   *)
  45.  
  46. PROCEDURE And (op1, op2 : BITSET) : BITSET;
  47. BEGIN
  48.   RETURN op1 * op2;
  49. END And;
  50.  
  51. PROCEDURE AndNot (op1, op2 : BITSET) : BITSET;
  52. BEGIN
  53.   RETURN op1 - op2;
  54. END AndNot;
  55.  
  56. PROCEDURE Or (op1, op2 : BITSET) : BITSET;
  57. BEGIN
  58.   RETURN op1 + op2;
  59. END Or;
  60.  
  61. PROCEDURE Xor (op1, op2 : BITSET) : BITSET;
  62. BEGIN
  63.   RETURN op1 / op2;
  64. END Xor;
  65.  
  66.  
  67. (*--------------------------------------*)
  68. (* Miscellaneous local procedures       *)
  69.  
  70. PROCEDURE Max (x, y : INTEGER) : INTEGER;
  71. BEGIN
  72.   IF x > y THEN
  73.     RETURN x;
  74.   ELSE
  75.     RETURN y;
  76.   END;
  77. END Max;
  78.  
  79.  
  80. PROCEDURE ConstrainExNum (VAR Number : ExNumType);
  81. (* Limit Number to be within MinNumber to MaxNumber and
  82.    eliminate any fractional portions. *)
  83. BEGIN
  84.   ExMin(Number, MaxNumber, Number);
  85.   ExMax(Number, MinNumber, Number);
  86.   ExTrunc(Number);
  87. END ConstrainExNum;
  88.  
  89.  
  90. PROCEDURE ExNumToLogical (Numb        : ExNumType;
  91.                           VAR Logical : LogicalType);
  92. VAR
  93.   DivScale : ExNumType;
  94.   Scale    : ExNumType;
  95.   Temp     : ExNumType;
  96.   Temp2    : ExNumType;
  97.   LogCnt   : INTEGER;
  98. BEGIN
  99.   (* Constrain op1, op2 to be within the logical number set *)
  100.   ConstrainExNum(Numb);
  101.  
  102.   (* translation scaling factor *)
  103.   ExNumb(65536, 0, 0, Scale);
  104.   ExDiv(DivScale, Ex1, Scale);
  105.  
  106.   (* perform conversion *)
  107.   LogCnt  := 0;
  108.   Logical := LogZero;
  109.   WHILE NOT IsZero(Numb) DO
  110.     ExMult(Temp2, Numb, DivScale);
  111.     ExTrunc(Temp2);
  112.     ExMult(Temp, Temp2, Scale);
  113.     ExSub(Temp, Numb, Temp);
  114.     IF LogCnt > LogicalSize THEN RETURN END;
  115.     Logical[LogCnt] := BITSET(ExToLongInt(Temp));
  116.     Numb := Temp2;
  117.     INC(LogCnt);
  118.   END;
  119. END ExNumToLogical;
  120.  
  121. PROCEDURE LogicalToExNum (Logical  : LogicalType;
  122.                           VAR Numb : ExNumType);
  123. VAR
  124.   Scale  : ExNumType;
  125.   Temp   : ExNumType;
  126.   LogCnt : INTEGER;
  127. BEGIN
  128.   (* translation scaling factor *)
  129.   ExNumb(65536, 0, 0, Scale);
  130.  
  131.   (* perform conversion *)
  132.   Numb := Ex0;
  133.   FOR LogCnt := LogicalSize TO 0 BY -1 DO
  134.     ExMult(Numb, Numb, Scale);
  135.     ExNumb(LONGINT(Logical[LogCnt]), 0, 0, Temp);
  136.     ExAdd(Numb, Numb, Temp);
  137.   END;
  138. END LogicalToExNum;
  139.  
  140.  
  141. (*--------------------------------------*)
  142. (* Local procedure to perform general   *)
  143. (* logical operations on ExNumbers.     *)
  144.  
  145. PROCEDURE LOp (VAR Result : ExNumType;
  146.                op1        : ExNumType;
  147.                Oper       : LogicalProc;
  148.                op2        : ExNumType);
  149. VAR
  150.   i : CARDINAL;
  151.   Lop1, Lop2 : LogicalType;
  152. BEGIN
  153.   (* Translate to logicals *)
  154.   ExNumToLogical(op1, Lop1);
  155.   ExNumToLogical(op2, Lop2);
  156.  
  157.   (* Operate on Lop1 and Lop2 one quad at a time *)
  158.   FOR i := 0 TO LogicalSize DO
  159.     Lop2[i] := Oper(Lop1[i], Lop2[i]);
  160.   END;
  161.  
  162.   (* Translate back the result *)
  163.   LogicalToExNum(Lop2, Result);
  164. END LOp;
  165.  
  166.  
  167. (*--------------------------------------*)
  168. (* Local procedure to perform general   *)
  169. (* single bit operations on ExNumbers.  *)
  170.  
  171. PROCEDURE LBit (VAR Result : ExNumType;
  172.                 number     : ExNumType;
  173.                 Oper       : LogicalProc;
  174.                 bitnum     : CARDINAL);
  175. VAR
  176.   Temp : ExNumType;
  177. BEGIN
  178.   (* Constrain number to be within the logical number set *)
  179.   ConstrainExNum(number);
  180.  
  181.   (* constrain bitnum from 0 to MaxBase2Bits *)
  182.   IF bitnum > MaxBase2Bits THEN
  183.     (* no bits are changed *)
  184.     Result := number;
  185.     RETURN;
  186.   END;
  187.  
  188.   (* calculate 2**bitnum *)
  189.   xtoi(Temp, Two, LONGINT(bitnum));
  190.  
  191.   (* set the bitnum bit position *)
  192.   LOp(Result, number, Oper, Temp);
  193. END LBit;
  194.  
  195.  
  196. (*--------------------------------------*)
  197. (* Local function to extract a bit from *)
  198. (* an ExNumber.                         *)
  199.  
  200. PROCEDURE BitSet (number : ExNumType;
  201.                   bitnum : CARDINAL) : BOOLEAN;
  202. VAR
  203.   Temp : ExNumType;
  204. BEGIN
  205.   (* Constrain number to be within the logical number set *)
  206.   ConstrainExNum(number);
  207.  
  208.   (* constrain bitnum from 0 to MaxBase2Bits - 1 *)
  209.   IF bitnum >= MaxBase2Bits THEN
  210.     (* assume FALSE *)
  211.     RETURN FALSE;
  212.   END;
  213.  
  214.   (* calculate 2**bitnum *)
  215.   xtoi(Temp, Two, LONGINT(bitnum));
  216.  
  217.   (* extract the bitnum bit *)
  218.   ExAnd(number, number, Temp);
  219.  
  220.   (* translate to boolean *)
  221.   RETURN NOT IsZero(number);
  222. END BitSet;
  223.  
  224.  
  225. (*--------------------------------------*)
  226. (* Local procedure to perform general   *)
  227. (* bit shifting operations on ExNumbers.*)
  228.  
  229. PROCEDURE LShift (VAR Result : ExNumType;
  230.                   number     : ExNumType;
  231.                   ExOper     : ExNumbProc;
  232.                   bits       : CARDINAL);
  233. VAR
  234.   Temp : ExNumType;
  235. BEGIN
  236.   (* Constrain number to be within the logical number set *)
  237.   ConstrainExNum(number);
  238.  
  239.   (* constrain bitnum from 0 to MaxBase2Bits *)
  240.   IF bits > MaxBase2Bits THEN
  241.     (* shifted out of range *)
  242.     Result := Ex0;
  243.     RETURN;
  244.   END;
  245.  
  246.   (* calculate 2**bits *)
  247.   xtoi(Temp, Two, LONGINT(bits));
  248.  
  249.   (* shift the number *)
  250.   ExOper(Result, number, Temp);
  251.  
  252.   (* Constrain number to be within the logical number set *)
  253.   ConstrainExNum(Result);
  254. END LShift;
  255.  
  256.  
  257. (*--------------------------------------*)
  258. (* Local procedure to perform general   *)
  259. (* bit rotation operations on ExNumbers.*)
  260.  
  261. PROCEDURE LRotate (VAR Result : ExNumType;
  262.                    number     : ExNumType;
  263.                    Shiftright : BOOLEAN;
  264.                    bits       : CARDINAL);
  265. VAR
  266.   ShiftCnt : CARDINAL;
  267.   SavedBit : BOOLEAN;
  268.   Half     : ExNumType;
  269. BEGIN
  270.   (* Constrain number to be within the logical number set *)
  271.   ConstrainExNum(number);
  272.  
  273.   (* constrain bitnum from 0 to MaxBase2Bits *)
  274.   bits := bits MOD (MaxBase2Bits + 1);
  275.   ExNumb(0, 5, 0, Half);
  276.  
  277.   FOR ShiftCnt := 1 TO bits DO
  278.     IF Shiftright THEN
  279.       (* save the bit to be shifted *)
  280.       SavedBit := BitSet(number, 0);
  281.  
  282.       (* shift the number right *)
  283.       ExMult(number, number, Half);
  284.       ExTrunc(number);
  285.       IF SavedBit THEN
  286.         ExSetBit(number, number, MaxBase2Bits-1);
  287.       END;
  288.     ELSE
  289.       (* save the bit to be shifted *)
  290.       SavedBit := BitSet(number, MaxBase2Bits-1);
  291.  
  292.       (* shift the number left *)
  293.       ExMult(number, number, Two);
  294.  
  295.       (* restore the saved bit *)
  296.       IF SavedBit THEN
  297.         ExSetBit(number, number, 0);
  298.       END;
  299.     END;
  300.  
  301.   END;
  302.  
  303.   (* Constrain number to be within the logical number set *)
  304.   Result := number;
  305.   ConstrainExNum(Result);
  306. END LRotate;
  307.  
  308.  
  309. (*--------------------------------------*)
  310. (* Exported procedures.                 *)
  311.  
  312. PROCEDURE ExAnd (VAR Result : ExNumType;
  313.                 op1, op2   : ExNumType);
  314. BEGIN
  315.   LOp(Result, op1, And, op2);
  316. END ExAnd;
  317.  
  318.  
  319. PROCEDURE ExOr (VAR Result : ExNumType;
  320.                op1, op2   : ExNumType);
  321. BEGIN
  322.   LOp(Result, op1, Or, op2);
  323. END ExOr;
  324.  
  325.  
  326. PROCEDURE ExXor (VAR Result : ExNumType;
  327.                  op1, op2   : ExNumType);
  328. BEGIN
  329.   LOp(Result, op1, Xor, op2);
  330. END ExXor;
  331.  
  332.  
  333. PROCEDURE ExIntDiv (VAR Result : ExNumType;
  334.                     op1, op2   : ExNumType);
  335. BEGIN
  336.   (* Constrain inputs to be integers *)
  337.   ConstrainExNum(op1); ConstrainExNum(op2);
  338.   ExDiv(Result, op1, op2);
  339.   ExTrunc(Result);
  340. END ExIntDiv;
  341.  
  342.  
  343. PROCEDURE ExMod (VAR Result : ExNumType;
  344.                  op1, op2   : ExNumType);
  345. BEGIN
  346.   (* Result := op1 - (op1 DIV op2) * op2 *)
  347.   ConstrainExNum(op1); ConstrainExNum(op2);
  348.   ExIntDiv(Result, op1, op2);
  349.   ExMult(Result, Result, op2);
  350.   ExSub(Result, op1, Result);
  351. END ExMod;
  352.  
  353.  
  354. PROCEDURE ExSetBit (VAR Result : ExNumType;
  355.                     number     : ExNumType;
  356.                     bitnum     : CARDINAL);
  357. BEGIN
  358.   LBit(Result, number, Or, bitnum);
  359. END ExSetBit;
  360.  
  361.  
  362. PROCEDURE ExClearBit (VAR Result : ExNumType;
  363.                       number     : ExNumType;
  364.                       bitnum     : CARDINAL);
  365. BEGIN
  366.   LBit(Result, number, AndNot, bitnum);
  367. END ExClearBit;
  368.  
  369.  
  370. PROCEDURE ExToggleBit (VAR Result : ExNumType;
  371.                        number     : ExNumType;
  372.                        bitnum     : CARDINAL);
  373. BEGIN
  374.   LBit(Result, number, Xor, bitnum);
  375. END ExToggleBit;
  376.  
  377.  
  378. PROCEDURE ExOnesComp (VAR Result : ExNumType;
  379.                       number     : ExNumType);
  380. BEGIN
  381.   (* Constrain number to be within the logical number set *)
  382.   ConstrainExNum(number);
  383.   IF number.Sign = positive THEN
  384.     (* Subtract from the maximum number *)
  385.     ExSub(Result, MaxNumber, number);
  386.   ELSE
  387.     (* Subtract from the minimum number *)
  388.     ExSub(Result, MinNumber, number);
  389.   END;
  390.  
  391.   (* Complement the sign bit *)
  392.   ExChgSign(Result);
  393. END ExOnesComp;
  394.  
  395.  
  396. PROCEDURE ExShl (VAR Result : ExNumType;
  397.                  number     : ExNumType;
  398.                  numbits    : CARDINAL);
  399. BEGIN
  400.   LShift(Result, number, ExMult, numbits);
  401.  
  402.   (* Determine the resultant sign *)
  403.   IF BitSet (Result, MaxBase2Bits-1) THEN
  404.     Result.Sign := negative;
  405.   ELSE
  406.     Result.Sign := positive;
  407.   END;
  408. END ExShl;
  409.  
  410.  
  411. PROCEDURE ExRol (VAR Result : ExNumType;
  412.                  number     : ExNumType;
  413.                  numbits    : CARDINAL);
  414. BEGIN
  415.   LRotate(Result, number, Left, numbits);
  416. END ExRol;
  417.  
  418.  
  419. PROCEDURE ExShr (VAR Result : ExNumType;
  420.                  number     : ExNumType;
  421.                  numbits    : CARDINAL);
  422. BEGIN
  423.   LShift(Result, number, ExDiv, numbits);
  424.   ExAbs(Result);  (* clear the sign *)
  425. END ExShr;
  426.  
  427.  
  428. PROCEDURE ExAshr (VAR Result : ExNumType;
  429.                   number     : ExNumType;
  430.                   numbits    : CARDINAL);
  431. VAR
  432.   ShiftCnt : CARDINAL;
  433.   SavedBit : BOOLEAN;
  434. BEGIN
  435.   (* Constrain number to be within the logical number set *)
  436.   ConstrainExNum(number);
  437.  
  438.   (* constrain bitnum from 0 to MaxBase2Bits *)
  439.   IF numbits > MaxBase2Bits THEN
  440.     (* shifted out of range *)
  441.     Result := Ex0;
  442.     RETURN;
  443.   END;
  444.  
  445.   (* set the SavedBit to the current sign *)
  446.   SavedBit := number.Sign = negative;
  447.  
  448.   (* shift the number *)
  449.   FOR ShiftCnt := 1 TO numbits DO
  450.     (* shift the number right *)
  451.     ExDiv(number, number, Two);
  452.  
  453.     (* restore the saved bit *)
  454.     IF SavedBit THEN
  455.       ExSetBit(number, number, MaxBase2Bits-1);
  456.     END;
  457.   END;
  458.  
  459.   (* truncate any fraction *)
  460.   Result := number;
  461.   ExTrunc(Result);
  462. END ExAshr;
  463.  
  464.  
  465. PROCEDURE ExRor (VAR Result : ExNumType;
  466.                  number     : ExNumType;
  467.                  numbits    : CARDINAL);
  468. BEGIN
  469.   LRotate(Result, number, Right, numbits);
  470. END ExRor;
  471.  
  472.  
  473. (*$S-*)
  474. PROCEDURE StrToExInt(S     : ARRAY OF CHAR;
  475.                      Base  : BaseType;
  476.                      VAR A : ExNumType);
  477. VAR
  478.   EndCnt, InCnt : INTEGER;
  479.   Multiplier    : INTEGER;
  480.   Scale, Temp   : ExNumType;
  481.  
  482.   PROCEDURE DigitIs() : LONGINT;
  483.   VAR
  484.     Str : ARRAY [0..1] OF CHAR;
  485.     Digits : LONGINT;
  486.   BEGIN
  487.     (* Extract a digit *)
  488.     Str[0] := S[InCnt]; Str[1] := 0C;
  489.     INC(InCnt);
  490.  
  491.     IF NOT ConvStrToNum(Str, Digits, Base, FALSE) THEN
  492.       ExStatus := IllegalNumber;
  493.       RETURN 0;
  494.     END;
  495.     RETURN Digits;
  496.   END DigitIs;
  497.  
  498. BEGIN
  499.   A := Ex0;
  500.   InCnt := 0;
  501.   EndCnt := LengthStr(S);
  502.   ExNumb(Base, 0, 0, Scale);
  503.  
  504.   (* skip leading blanks *)
  505.   WHILE (InCnt < EndCnt) & (S[InCnt] = ' ') DO INC(InCnt) END;
  506.  
  507.   WHILE (InCnt < EndCnt) & (ExStatus # IllegalNumber) DO
  508.     ExNumb(DigitIs(), 0, 0, Temp);
  509.     ExMult(A, A, Scale);
  510.     ExAdd(A, A, Temp);
  511.   END;
  512. END StrToExInt;
  513.  
  514.  
  515. PROCEDURE ExIntToStr(A     : ExNumType;
  516.                      Base  : BaseType;
  517.                      VAR S : ARRAY OF CHAR);
  518. VAR
  519.   InCnt : INTEGER;
  520.   InvScale, Scale, Temp, Temp2 : ExNumType;
  521.  
  522.   PROCEDURE PutDigits(Numb : LONGCARD);
  523.   VAR
  524.     Str : ARRAY [0..80] OF CHAR;
  525.     Ok  : BOOLEAN;
  526.   BEGIN
  527.     Ok := ConvNumToStr(Str, Numb, Base, FALSE, 4, '0');
  528.     InsertSubStr(S, Str, 0);
  529.   END PutDigits;
  530.  
  531. BEGIN
  532.   (* Constrain number to be within the logical number set *)
  533.   ConstrainExNum(A);
  534.  
  535.   S := "";
  536.   InCnt := 0;
  537.   ExNumb(Base, 0, 0, Scale);
  538.   xtoi(Scale, Scale, 4);
  539.   ExDiv(InvScale, Ex1, Scale);
  540.  
  541.   (* translate number to a string *)
  542.   REPEAT
  543.     (* Temp := A MOD Scale *)
  544.     ExMult(Temp2, A, InvScale);
  545.     ExTrunc(Temp2);
  546.     ExMult(Temp, Temp2, Scale);
  547.     ExSub(Temp, A, Temp);
  548.  
  549.     (* Translate to character *)
  550.     PutDigits(ExToLongCard(Temp));
  551.  
  552.     (* Reduce A by scaling factor *)
  553.     A := Temp2;
  554.   UNTIL IsZero(A);
  555. END ExIntToStr;
  556.  
  557.  
  558. BEGIN
  559.   (* create the number 2 *)
  560.   ExNumb(2, 0, 0, Two);
  561.  
  562.   (* Initialize the maximum number *)
  563.   xtoi(MaxNumber, Two, MaxBase2Bits);
  564.   ExSub(MaxNumber, MaxNumber, Ex1);
  565.  
  566.   (* Initialize the minimum number *)
  567.   MinNumber := MaxNumber;
  568.   ExChgSign(MinNumber);
  569.  
  570.   (* Initialize the zero logical *)
  571.   FOR Cnt := 0 TO LogicalSize DO
  572.     LogZero[Cnt] := {};
  573.   END;
  574. END ExIntegers.
  575.